from django.core.files.storage import Storage

from fdfs_client.client import Fdfs_client
from django.conf import settings


class FastDFSStorage(Storage):
    """自定义文件存储系统，实现文件转存到fdfs中"""

    def __init__(self, client_conf=None, base_url=None):
        # 重写构造方法， 当在存储数据时， django会自动调用， 但不会传参进来
        self.client_conf = client_conf or settings.FDFS_CLIENT_CONF
        self.base_url = base_url or settings.FDFS_BASE_URL

    def _open(self, name, mode='rb'):
        # 打开文件时调用的， 因为此时只有文件上传， 没有文件打开， 但又必须实现， 只能pass
        pass

    def _save(self, name, content):
        """
        存储文件时调用的
        :param name: 要存储文件的名字
        :param content: 要存储文件的对象，file类型的， 需要调用read（）读取出文件的内容
        :return:file_id
        """

        # 创建fdfs客户端对象， 和tracker 进行交互
        client = Fdfs_client(self.client_conf)
        # 调用上传方法
        ret = client.upload_by_buffer(content.read())
        # 判断上传是否成功
        if ret.get('Status') != 'Upload successed.':
            raise Exception('upload file failed')
        # 返回file_id, 模型类会自动读取file_id, 存储到模型类的ImageFiled字段
        file_id = ret.get('Remote file_id')
        return file_id

    def exists(self, name):
        """
        判断文件是否已经在本地存储， 返回True， 表示文件已经自本地存储中，django就不会再存储， 返回False， django
        才会积极存储
        :param name:要上传的文件的名字
        :return:
        """
        return False

    def url(self, name):
        """
        返回文件的全路径， 该方法是提供给模型类中ImageField字段对应的属性调用的
        :param name:要返回全路径的文件的名字
        :return:
        """
        return self.base_url + name
